package com.zhouzi.zhaoyang.base

import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.os.Bundle
import androidx.annotation.Nullable
import cn.jpush.android.api.JPushInterface
import com.afollestad.materialdialogs.MaterialDialog
import com.google.zxing.integration.android.IntentIntegrator
import com.orhanobut.logger.AndroidLogAdapter
import com.orhanobut.logger.Logger
import com.orhanobut.logger.PrettyFormatStrategy
import com.tencent.bugly.crashreport.CrashReport
import com.zhouzi.zhaoyang.bean.OrderDetailBean
import com.zhouzi.zhaoyang.bean.PushGetOrderBean
import com.zhouzi.zhaoyang.service.PrintService
import com.zhouzi.zhaoyang.service.VoiceService
import com.zhouzi.zhaoyang.ui.activity.MyScanActivity
import com.zhouzi.zhaoyang.util.*
import com.zhouzi.zhaoyang.util.print.PrinterUtil
import com.zhouzi.zhaoyang.util.print.USBPrinter
import com.zhy.http.okhttp.OkHttpUtils
import okhttp3.OkHttpClient
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.properties.Delegates


/**
 * Created by ZhouZi on 2019/7/4.
 * time:11:44
 * ----------Dragon be here!----------/
 * 　　　┏┓　　 ┏┓
 * 　　┏┛┻━━━┛┻┓━━━
 * 　　┃　　　　　 ┃
 * 　　┃　　　━　  ┃
 * 　　┃　┳┛　┗┳
 * 　　┃　　　　　 ┃
 * 　　┃　　　┻　  ┃
 * 　　┃　　　　   ┃
 * 　　┗━┓　　　┏━┛Code is far away from bug with the animal protecting
 * 　　　　┃　　　┃    神兽保佑,代码无bug
 * 　　　　┃　　　┃
 * 　　　　┃　　　┗━━━┓
 * 　　　　┃　　　　　　┣┓
 * 　　　　┃　　　　　　　┏┛
 * 　　　　┗┓┓┏━┳┓┏┛━━━━━
 * 　　　　　┃┫┫　┃┫┫
 * 　　　　　┗┻┛　┗┻┛
 * ━━━━━━━━━━━神兽出没━━━━━━━━━━━━━━
 */
class App : Application() {

    private var printer: USBPrinter? = null

    companion object {
        var mContext: Context by Delegates.notNull()
            private set
        private var instance: App? = null
        fun instance() = instance!!

    }

    override fun onCreate() {
        super.onCreate()
        instance = this
        mContext = applicationContext
        initLogger()
        registerActivirtListener()
        initPrinter()

        /**
         * bugly
         * */
        CrashReport.initCrashReport(applicationContext, "65e4160a1b", true)

        val okHttpClient = OkHttpClient.Builder()
            //                .addInterceptor(new LoggerInterceptor("TAG"))
            .connectTimeout(10000L, TimeUnit.MILLISECONDS)
            .readTimeout(10000L, TimeUnit.MILLISECONDS)
            //其他配置
            .build()

        OkHttpUtils.initClient(okHttpClient)


        JPushInterface.setDebugMode(true)
        JPushInterface.init(this)

        val registrationID = JPushInterface.getRegistrationID(this)
//        SPUtils.getInstance().putValue("cbPrintSettings1" , 2)
//        SPUtils.getInstance().putValue("cbPrintSettings2" , 2)
//        SPUtils.getInstance().putValue("cbPrintSettings3" , 2)
//        SPUtils.getInstance().putValue("cbPrintSettings4" , 2)


    }


    public fun initPrinter(): Unit {
        printer = USBPrinter.getInstance()
        printer?.initPrinter(this)
    }

    public fun printOrder(data: OrderDetailBean): Unit {
        var mode: Int = SPUtils.getInstance().getValue("cbPrintSettingsPrintMode", 1) as Int

        val util = PrinterUtil(this)
        val line = ArrayList<String>()

        for (index in 1..mode) {
            line.add("门店名称: " + data.storeName)
            line.add("商户单号: " + data.outTradeNo)
            line.add(PrintFormatUtils.getQrCodeCmd(data.outTradeNo) + "\n")
            line.add("总金额：" + Calculator.fen2Yuan(data.totalFee!!.toLong()))
            if (data.settlementTotalFee!! > 0) {
                line.add("实收金额：" + Calculator.fen2Yuan(data.settlementTotalFee!!.toLong()))
            }
            if (data.consumeFee != null) {
                line.add("房费：" + Calculator.fen2Yuan(data.consumeFee!!.toLong()))
            }
            if (data.depositFee != null) {
                line.add("押金：" + Calculator.fen2Yuan(data.depositFee!!.toLong()))
            }
            line.add("实付金额：" + Calculator.fen2Yuan(data.realFee!!.toLong()))
            line.add("支付方式：" + data.payType)
            line.add("支付状态：" + data.status)
            line.add("店员：" + data.userName)
//            line.add("设备号："+data.deviceNo)


            line.add("下单时间: " + data.orderTime)
            line.add("打印时间：" + DateUtil.getStringToday())
            line.add(
                "签名：" + "\n\n\n\n" +
                        "\n" +
                        "\n"
            )


        }

        util.createData(line)
    }

    public fun printOrderWithNormal(data: OrderDetailBean): Unit {
        var mode: Int = SPUtils.getInstance().getValue("cbPrintSettingsPrintMode", 1) as Int

        val util = PrinterUtil(this)
        val line = ArrayList<String>()

        for (index in 1..mode) {
            line.add("门店名称: " + data.storeName)
            line.add("商户单号: " + data.outTradeNo)
            line.add(PrintFormatUtils.getQrCodeCmd(data.outTradeNo) + "\n")
            line.add("订单金额：" + Calculator.fen2Yuan(data.totalFee!!.toLong()))
            if (data.settlementTotalFee!! > 0) {
                line.add("实收金额：" + Calculator.fen2Yuan(data.settlementTotalFee!!.toLong()))
            }
            line.add("实付金额：" + Calculator.fen2Yuan(data.realFee!!.toLong()))
            line.add("支付方式：" + data.payType)
            line.add("支付状态：" + data.status)
//            line.add("设备号："+data.deviceNo)
            line.add("店员：" + data.userName)


            line.add("下单时间: " + data.orderTime)
            line.add("打印时间：" +  DateUtil.getStringToday())
            line.add(
                "签名：" + "\n\n\n\n" +
                        "\n" +
                        "\n"
            )


        }

        util.createData(line)
    }

    public fun printOrderWithRV(data: OrderDetailBean): Unit {
        var mode: Int = SPUtils.getInstance().getValue("cbPrintSettingsPrintMode", 1) as Int

        val util = PrinterUtil(this)
        val line = ArrayList<String>()

        for (index in 1..mode) {
            line.add("补打订单 " )
            line.add("门店名称: " + data.storeName)
            line.add("商户单号: " + data.outTradeNo)
            line.add(PrintFormatUtils.getQrCodeCmd(data.outTradeNo) + "\n")
            line.add("订单金额：" + Calculator.fen2Yuan(data.totalFee!!.toLong()))
            if (data.settlementTotalFee!! > 0) {
                line.add("实收金额：" + Calculator.fen2Yuan(data.settlementTotalFee!!.toLong()))
            }
            line.add("实付金额：" + Calculator.fen2Yuan(data.realFee!!.toLong()))
            line.add("支付方式：" + data.payType)
            line.add("支付状态：" + data.status)
//            line.add("设备号："+data.deviceNo)
            line.add("店员：" + data.userName)


            line.add("下单时间: " + data.orderTime)
            line.add("打印时间：" +  DateUtil.getStringToday())
            line.add(
                "签名：" + "\n\n\n\n" +
                        "\n" +
                        "\n"
            )


        }

        util.createData(line)
    }

    public fun printOrderWithReturnMoney(data: OrderDetailBean): Unit {
        var mode: Int = SPUtils.getInstance().getValue("cbPrintSettingsPrintMode", 1) as Int

        val util = PrinterUtil(this)
        val line = ArrayList<String>()


        for (index in 1..mode) {
            line.add("退款 " )
            line.add("门店名称: " + data.storeName)
            line.add("商户单号: " + data.outTradeNo)
            line.add(PrintFormatUtils.getQrCodeCmd(data.outTradeNo) + "\n")
            line.add("订单金额：" + Calculator.fen2Yuan(data.totalFee!!.toLong()))
            if (data.settlementTotalFee!! > 0) {
                line.add("实收金额：" + Calculator.fen2Yuan(data.settlementTotalFee!!.toLong()))
            }
            line.add("实付金额：" + Calculator.fen2Yuan(data.realFee!!.toLong()))
            line.add("支付方式：" + data.payType)
            line.add("支付状态：" + data.status)
//            line.add("设备号："+data.deviceNo)
            line.add("退款店员：" + data.userName)


            line.add("下单时间: " + data.orderTime)
            line.add("打印时间：" + DateUtil.getStringToday())
            line.add(
                "签名：" + "\n\n\n\n" +
                        "\n" +
                        "\n"
            )


        }

        util.createData(line)
    }


    public fun pushOrder(pushGetOrderBean: PushGetOrderBean): Unit {
        var mode: Int = SPUtils.getInstance().getValue("cbPrintSettingsPrintMode", 1) as Int

        val util = PrinterUtil(this)
        val line = ArrayList<String>()
        val data = pushGetOrderBean.result
        for (index in 1..mode) {
            line.add("门店名称: " + data?.storeName)
            line.add("商户单号: " + data?.outTradeNo)
            line.add(PrintFormatUtils.getQrCodeCmd(data?.outTradeNo) + "\n")
            line.add("订单金额：" + Calculator.fen2Yuan(data?.totalFee!!.toLong()))
            if (data.settlementTotalFee!! > 0) {
                line.add("实收金额：" + Calculator.fen2Yuan(data.settlementTotalFee!!.toLong()))
            }
            line.add("实付金额：" + Calculator.fen2Yuan(data?.realFee!!.toLong()))
            line.add("支付方式：" + data?.payType)
            line.add("支付状态：" + data?.status)
//            line.add("设备号："+data.deviceNo)
            line.add("退款店员：" + data?.userName)


            line.add("下单时间: " + data?.orderTime)
            line.add("打印时间：" + DateUtil.getStringToday())
            line.add(
                "签名：" + "\n\n\n\n" +
                        "\n" +
                        "\n"
            )


        }

        util.createData(line)
    }


    public fun scan(activity: BaseActivity) {

        val intent = Intent(mContext, VoiceService::class.java)
        intent.putExtra("voiceStr", "请对准二维码")
        startService(intent)


        IntentIntegrator(activity)
            .setCaptureActivity(MyScanActivity().javaClass)
            .setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES)// 扫码的类型,可选：一维码，二维码，一/二维码
            .setPrompt("请对准二维码")// 设置提示语
            .setCameraId(0)// 选择摄像头,可使用前置或者后置
            .setBeepEnabled(false)// 是否开启声音,扫完码之后会"哔"的一声
            .setBarcodeImageEnabled(true)// 扫完码之后生成二维码的图片
            .initiateScan()// 初始化扫码

    }


    operator fun Date.get(position: Int): Int {
        val calendar = GregorianCalendar()
        calendar.time = this
        var value = 0
        when (position) {
            0 -> value = calendar.get(Calendar.YEAR)
            1 -> value = calendar.get(Calendar.MONTH) + 1
            2 -> value = calendar.get(Calendar.DAY_OF_MONTH)
            3 -> value = calendar.get(Calendar.HOUR_OF_DAY)
            4 -> value = calendar.get(Calendar.MINUTE)
            5 -> value = calendar.get(Calendar.SECOND)
        }
        return value
    }


    public fun getUsbDeviceList(): MutableList<UsbDevice> {
        val usbDevices = mutableListOf<UsbDevice>()
        val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
        val devices = usbManager.deviceList
        val deviceIterator = devices.values.iterator()
        if (devices.size > 0) {
            while (deviceIterator.hasNext()) {
                val usbDevice = deviceIterator.next()
                if (checkUsbDevicePidVid(usbDevice))
                    usbDevices.add(usbDevice)
            }
        }
        return usbDevices
    }

    private fun checkUsbDevicePidVid(dev: UsbDevice): Boolean {
        val pid = dev.productId
        val vid = dev.vendorId
        return (vid == 34918 && pid == 256 || vid == 1137 && pid == 85
                || vid == 6790 && pid == 30084
                || vid == 26728 && pid == 256 || vid == 26728 && pid == 512
                || vid == 26728 && pid == 256 || vid == 26728 && pid == 768
                || vid == 26728 && pid == 1024 || vid == 26728 && pid == 1280
                || vid == 26728 && pid == 1536)
    }

    public fun printProductInformation(orderDetail: OrderDetailBean) {
        App.instance().initPrinter()
        val devices = getUsbDeviceList()
        if (devices.size == 0) {
            return
        }
        val deviceNames = devices.map {
            it.deviceName
        }
        MaterialDialog.Builder(mContext)
            .items(deviceNames)
            .itemsCallback { dialog, itemView, position, text ->
                val intent = Intent(mContext, PrintService::class.java)
                intent.putExtra("status", PrintService.CONNECT_DEVICE)
                intent.putExtra("usbDevice", devices[position])

                // 实体类
                putEntity(intent, orderDetail)

                startService(intent)
            }.show()


        App.instance().printOrder(orderDetail)

        startService(Intent(mContext, PrintService::class.java))

    }

    public fun putEntity(
        intent: Intent,
        orderDetail: OrderDetailBean
    ) {
        intent.putExtra("storeName", orderDetail.storeName)
        intent.putExtra("realFee", orderDetail.realFee)
    }


    private fun initLogger() {
        val formatStrategy = PrettyFormatStrategy.newBuilder()
            .showThreadInfo(true) //是否显示线程信息
            .methodCount(1) //设置Log中调用堆栈的函数行数，默认值为 2，即显示2层
            .methodOffset(0)                // 设置调用堆栈的函数偏移值，默认值为 0，即从打印该Log的函数开始输出堆栈信息
            .tag("zhouzi")
            .build()
        Logger.addLogAdapter(object : AndroidLogAdapter(formatStrategy) {
            override fun isLoggable(priority: Int, @Nullable tag: String?): Boolean {
                return true //设置是否打印日志
            }
        })
    }


    private fun registerActivirtListener() {
        registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
            override fun onActivityPaused(activity: Activity?) {
            }

            override fun onActivityResumed(activity: Activity?) {
            }

            override fun onActivityStarted(activity: Activity?) {
            }

            override fun onActivityDestroyed(activity: Activity?) {
                AppManager.getInstance().removeActivity(activity)
            }

            override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
            }

            override fun onActivityStopped(activity: Activity?) {
            }

            override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
                AppManager.getInstance().addActivity(activity)
            }

        })
    }

}